﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace DS2171Utils.Plug
{
   public  class Pluginner
    {

       public IList<PlugingHost> PluginsCaricati { get; set; }

       private static List<Assembly> LoadPlugInAssemblies()
       {
           DirectoryInfo dInfo = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, "Plugins"));
           FileInfo[] files = dInfo.GetFiles("*.dll");
           List<Assembly> plugInAssemblyList = new List<Assembly>();

           if (null != files)
           {
               foreach (FileInfo file in files)
               {
                   plugInAssemblyList.Add(Assembly.LoadFile(file.FullName));
               }
           }

           return plugInAssemblyList;

       }//fM


       static List<IPlugExecuter> GetPlugIns(List<Assembly> assemblies)
       {
           List<Type> availableTypes = new List<Type>();

           foreach (Assembly currentAssembly in assemblies)
               availableTypes.AddRange(currentAssembly.GetTypes());

           // get a list of objects that implement the ICalculator interface AND 
           // have the CalculationPlugInAttribute
           List<Type> calculatorList = availableTypes.FindAll(delegate(Type t)
           {
               List<Type> interfaceTypes = new List<Type>(t.GetInterfaces());
               object[] arr = t.GetCustomAttributes(typeof(PlugInAttribute), true);
               return !(arr == null || arr.Length == 0) && interfaceTypes.Contains(typeof(IPlugExecuter));
           });

           // convert the list of Objects to an instantiated list of ICalculators
           return calculatorList.ConvertAll<IPlugExecuter>(delegate(Type t) { return Activator.CreateInstance(t) as IPlugExecuter; });

       }//fM


       public  void Reload()
       {

           if (null == PluginsCaricati)
               PluginsCaricati = new List<PlugingHost>();
           else
               PluginsCaricati.Clear();

           //PluginsCaricati.Add(new PlugingHost()); // load the default
           List<Assembly> plugInAssemblies = LoadPlugInAssemblies();
           List<IPlugExecuter> plugIns = GetPlugIns(plugInAssemblies);

           foreach (IPlugExecuter plug in plugIns)
           {
               PluginsCaricati.Add(new PlugingHost(plug));
           }
       }//fM



       [PlugInAttribute("This plug-in will add two numbers together")]
       class Adder : IPlugExecuter
       {
           #region  Members

           public bool Execute()
           {
               return true;
           }

           public char GetSymbol()
           {
               return '+';
           }

           #endregion

       }


    }//fC
}
